package com.bdqn.util;

import cn.hutool.core.util.StrUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * DateFormat不是线程安全的，因此通过此工具类并每个线程准备一个副本
 *
 * @author LILIBO
 * @since 2021-06-24
 */
public class DateUtil {

    private final static Logger logger = LoggerFactory.getLogger(DateUtil.class);

    public final static String FULL_HOUR_TIME = " 23:59:59";
    /**
     * 日期格式 -- "年-月-日" 如：2001-01-01
     */
    public final static String YYYY_MM_DD = "yyyy-MM-dd";
    public final static String CN_YYYY_MM_DD = "YYYY年M月d日";

    public final static String YYYYMMDD = "yyyyMMdd";
    public final static String YYMMDD = "yyMMdd";
    public final static String YYMMDDHHMM = "yyMMddHHmm";
    public final static String HHMM = "HH:MM";

    public final static String YYYY = "yyyy";
    public final static String MM = "MM";
    public final static String DD = "dd";

    public final static String YYYYMMDDHH = "yyyyMMddHH";
    /**
     * 日期格式 -- "年-月-日 时:分" 如：2001-01-01 20:20
     */
    public final static String YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
    /**
     * 日期格式 -- "年-月-日 时:分:秒" 如：2001-01-01 20:20:00
     */
    public final static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    public final static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
    public final static String YYMMDDHHMMSS = "yyMMddHHmmss";

    public final static String YYYYMMDDHHMMSSSS = "yyyyMMddHHmmssSS";
    /**
     * 返回 170505100000123 两位年月日时分秒毫秒
     */
    public final static String YYMMDDHHMMSSSSS = "yyMMddHHmmssSSS";
    public final static int WEEK_PREFIX_ZHOU = 0;
    public final static int WEEK_PREFIX_XINGQI = 1;
    public final static boolean WEEK_START_SUN = true;
    public final static boolean WEEK_START_MON = false;

    /**
     * 日期格式 -- "年-月" 如：2001-01
     */
    public static final String Y_M = "yyyy-MM";
    /**
     * 日期格式 -- "年月" 如：200101
     */
    public static final String YM = "yyyyMM";
    /**
     * 日期格式 -- "日期" 如：01
     */
    public static final String D = "dd";
    /**
     * 日期格式 -- "年-月-日 时" 如：2001-01-01 20
     */
    public static final String Y_M_D_HH = "yyyy-MM-dd HH";
    /**
     * 日期格式 -- "月-日 时:分" 如：01-01 20:20
     */
    public static final String M_D_H_MM = "MM-dd HH:mm";
    /**
     * 日期格式 -- "月日" 如：0101
     */
    public static final String MD = "MMdd";
    /**
     * 日期格式(中国格式) -- "点分" 如：9点10分
     */
    public static final String HH_MM_CH = "HH点mm分";

    /**
     * 日期
     */
    public final static long DAY = 1000 * 60 * 60 * 24;

    /**
     * 小时
     */
    public final static long HOUR = 1000 * 60 * 60;

    /**
     * 分钟
     */
    public final static long MINUTE = 1000 * 60;

    /**
     * 秒
     */
    public final static long SECOND = 1000;

    /**
     * 校准时区
     */
    public static final long TIME_ZONE_OFFSET_MILLIS = TimeZone.getDefault().getRawOffset();

    private static final Map<String, ThreadLocal<SimpleDateFormat>> pool = new HashMap<String, ThreadLocal<SimpleDateFormat>>();

    private static final Object lock = new Object();

    public static SimpleDateFormat getDateFormat(String pattern) {
        ThreadLocal<SimpleDateFormat> tl = pool.get(pattern);
        if (tl == null) {
            synchronized (lock) {
                tl = pool.get(pattern);
                if (tl == null) {
                    final String p = pattern;
                    tl = new ThreadLocal<SimpleDateFormat>() {
                        @Override
                        protected synchronized SimpleDateFormat initialValue() {
                            return new SimpleDateFormat(p);
                        }
                    };
                    pool.put(p, tl);
                }
            }
        }
        return tl.get();
    }

    /**
     * 获得现在时间long类型
     *
     * @return
     */
    public static long getNowTimeLong() {
        return System.currentTimeMillis();
    }

    /**
     * 获得当前日期Date型
     *
     * @return
     */
    public static Date getNowDate() {
        Date date = new Date();
        String dateString = getDateFormat(YYYY_MM_DD).format(date);
        try {
            date = getDateFormat(YYYY_MM_DD).parse(dateString);
        } catch (ParseException e) {
            logger.error("ParseException", e);
        }
        return date;
    }

    /**
     * 获得当前日期long类型
     *
     * @return
     */
    public static long getNowDateLong() {
        return getNowDate().getTime();
    }

    /**
     * 获得日期long类型
     *
     * @param dateString 需要转换的日期
     * @return
     */
    public static long getDateLong(String dateString) {
        Date date;
        try {
            date = getDateFormat(YYYY_MM_DD).parse(dateString);
        } catch (ParseException e) {
            date = new Date();
            logger.error("ParseException", e);
        }
        return date.getTime();
    }

    /**
     * 获得时间long类型
     *
     * @param timeString 需要转换的时间
     * @return
     */
    public static long getTimeLong(String timeString) {
        Date date = null;
        try {
            date = getDateFormat(YYYY_MM_DD_HH_MM_SS).parse(timeString);
        } catch (ParseException e) {
            date = new Date();
            logger.error("ParseException", e);
        }
        return date.getTime();
    }

    /**
     * 获取当前日期，不带横线
     *
     * @return
     */
    public static String getNowDateStringNOLine() {
        return getDateFormat(YYYYMMDD).format(new Date());
    }

    /**
     * 获取指定日期，带横线
     *
     * @return
     */
    public static String getDateStringLine(Date date) {
        return getDateFormat(YYYY_MM_DD).format(date);
    }

    public static String getDateStringYyyyMMddHHLine(Date date) {
        return getDateFormat(YYYY_MM_DD_HH_MM).format(date);
    }

    /**
     * 获取指定日期，不带横线
     *
     * @return
     */
    public static String getDateStringNOLine(Date date) {
        return getDateFormat(YYYYMMDD).format(date);
    }

    public static String getDateStringYYYYMMDDHH(Date date) {
        return getDateFormat(YYYYMMDDHH).format(date);
    }

    /**
     * 获取当前时间
     *
     * @return YYYY_MM_DD_HH_MM_SS
     */
    public static String getNowString() {
        return getDateFormat(YYYY_MM_DD_HH_MM_SS).format(new Date());
    }

    /**
     * 获取当前时间，不带横线
     * 格式：YYYYMMDDHHMMSS
     *
     * @return
     */
    public static String getNowStringNOLine() {
        return getDateFormat(YYYYMMDDHHMMSS).format(new Date());
    }

    /**
     * 获取当前时间，不带横线
     * 格式：YYYYMMDDHHMMSSSS
     *
     * @return
     */
    public static String getNowStringNOLineMs() {
        return getDateFormat(YYYYMMDDHHMMSSSS).format(new Date());
    }

    /**
     * 获取date，不带横线
     * 格式：YYYYMMDDHHMMSS
     *
     * @return
     */
    public static String getDateTimeStringNOLine(Date date) {
        return getDateFormat(YYYYMMDDHHMMSS).format(date);
    }

    /**
     * 获取当前日期
     * 格式：YYYY_MM_DD
     *
     * @return
     */
    public static String getNowDateString() {
        return getDateFormat(YYYY_MM_DD).format(new Date());
    }

    /**
     * 获取当前年
     * 格式：YYYY_MM_DD
     *
     * @return
     */
    public static String getNowDateYear() {
        return getDateFormat(YYYY).format(new Date());
    }

    /**
     * 获取当前月
     * 格式：YYYY_MM_DD
     *
     * @return
     */
    public static String getNowDateMonth() {
        return getDateFormat(MM).format(new Date());
    }

    /**
     * 获取当前日
     * 格式：YYYY_MM_DD
     *
     * @return
     */
    public static String getNowDateDay() {
        return getDateFormat(DD).format(new Date());
    }

    /**
     * 获取时间字符串<br/>
     * 格式：yyyy-MM-dd HH:mm
     *
     * @param time
     * @return
     */
    public static String getLongDateString(Date time) {
        return getDateFormat(YYYY_MM_DD_HH_MM).format(time);
    }

    /**
     * 获取时间字符串<br/>
     * 格式：yyyy-MM-dd HH:mm:ss
     *
     * @param time
     * @return
     */
    public static String getTimeString(Date time) {
        return getDateFormat(YYYY_MM_DD_HH_MM_SS).format(time);
    }

    /**
     * 获取日期字符串
     * 格式：YYYY_MM_DD
     *
     * @param time
     * @return
     */
    public static String getDateString(Date time) {
        return getDateFormat(YYYY_MM_DD).format(time);
    }

    public static String getTomorrowString(String format) {
        Date tomorrow = getDateBefore(new Date(), -1);
        return getDateFormat(format).format(tomorrow);
    }

    /**
     * 获取日期格式yyyy-MM-dd
     *
     * @param time
     * @return
     */
    public static Date getDateDate(String time) {
        Date d = null;
        try {
            d = getDateFormat(YYYY_MM_DD).parse(time);
        } catch (ParseException e) {
            logger.error("时间格式转换错误", e);
        }
        return d;
    }

    /**
     * 获取日期格式 yyyy-MM-dd hh:mm:ss
     *
     * @param time
     * @return
     * @throws ParseException
     */
    public static Date getTimeDate(String time) {
        Date d = null;
        try {
            d = getDateFormat(YYYY_MM_DD_HH_MM_SS).parse(time);
        } catch (ParseException e) {
            logger.error("格式转换错误", e);
        }
        return d;
    }

    /**
     * 获取日期格式 yyyy-MM-dd hh:mm
     *
     * @param time
     * @return
     * @throws ParseException
     */
    public static Date getTimeDateNoSecond(String time) {
        Date d = null;
        try {
            d = getDateFormat(YYYY_MM_DD_HH_MM).parse(time);
        } catch (ParseException e) {
            logger.error("格式转换错误", e);
        }
        return d;
    }

    /**
     * 获取一个月之前的日期
     *
     * @param time
     * @return
     */
    public static Date getLastMonthTime(Date time) {
        return getTimeBefore(time, 1, Calendar.MONTH);
    }

    /**
     * 获取一指定天数之前的时间
     *
     * @param d
     * @param day 增减的数字(之前日期为正;之后日期为负)
     * @return
     */
    public static Date getDateBefore(Date d, int day) {
        return getTimeBefore(d, day, Calendar.DATE);
    }

    /**
     * 获取指定天数之前的时间字符串
     *
     * @param d
     * @param day 增减的数字(之前日期为正;之后日期为负)
     * @return YYYY_MM_DD_HH_MM_SS
     */
    public static String getDateStringBefore(Date d, int day) {
        Date date = getDateBefore(d, day);
        return getDateFormat(YYYY_MM_DD_HH_MM_SS).format(date);
    }

    /**
     * 获取指定天数之前的时间字符串
     *
     * @param d 日期
     * @param day 增减的数字(之前日期为正;之后日期为负)
     * @param format 返回的日期格式
     * @return format
     */
    public static String getDateStringBefore(Date d, int day, String format) {
        Date date = getDateBefore(d, day);
        return getDateFormat(format).format(date);
    }

    /**
     * 获取指定天数之前的时间字符串
     *
     * @param dateStr 日期 YYYY_MM_DD HH_MM_SS
     * @param day 增减的数字(之前日期为正;之后日期为负)
     * @param format 返回的日期格式
     * @return format
     */
    public static String getDateStringBefore(String dateStr, int day, String format) {
        Date date;
        try {
            date = getDateFormat(YYYY_MM_DD).parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
            date = new Date();
        }
        date = getDateBefore(date, day);
        return getDateFormat(format).format(date);
    }

    /**
     * 获取日期 yyyyMMddHHmmss
     *
     * @param date
     * @return
     */
    public static Date parseDateNoLine(String date) {
        Date d = null;
        try {
            d = getDateFormat(YYYYMMDDHHMMSS).parse(date);
        } catch (ParseException e) {
            logger.error("格式转换错误", e);
        }
        return d;
    }

    /**
     * 获取日期 yyyy_mm_dd
     *
     * @param dateLong 需要转换的日期long
     * @return
     */
    public static String formatDateLong(long dateLong) {
        Date date = new Date(dateLong);
        return format(YYYY_MM_DD, date);
    }

    /**
     * 获取中国年月日
     *
     * @param milliseconds
     * @return
     */
    public static String formatChinaDate(long milliseconds) {
        return formatChinaDate(new Date(milliseconds));
    }

    public static String formatChinaDate(Date date) {
        return format(CN_YYYY_MM_DD, date);
    }

    /**
     * 获取日期 yyyy_mm_dd HH:mm:ss
     *
     * @param timeLong 需要转换的时间long
     * @return
     */
    public static String formatTimeLong(long timeLong) {
        Date date = new Date(timeLong);
        return format(YYYY_MM_DD_HH_MM_SS, date);
    }

    /**
     * 获取日期
     *
     * @param pattern 格式
     * @param timeLong 需要转换的时间long
     * @return
     */
    public static String formatLong(String pattern, long timeLong) {
        Date date = new Date(timeLong);
        return format(pattern, date);
    }

    /**
     * 获取日期 yyyy_mm_dd HH:mm
     *
     * @param timeLong 需要转换的时间long
     * @return
     */
    public static String formatTimeLongNoSecond(long timeLong) {
        Date date = new Date(timeLong);
        return format(YYYY_MM_DD_HH_MM, date);
    }

    /**
     * 获取昨天日期
     *
     * @return
     */
    public static Date getYesterday() {
        return getDateBefore(new Date(), 1);
    }

    /**
     * 获取昨天日期 yyyy-MM-dd
     *
     * @return
     */
    public static String getYesterDayString() {
        Date yesterday = getYesterday();
        return getDateString(yesterday);
    }

    /**
     * 获取某天全时间，date+" 23:59:59"
     *
     * @param date
     * @return
     */
    public static String getFullDayString(String date) {
        return date + FULL_HOUR_TIME;
    }

    /**
     * 查询一段时间内所有日期
     *
     * @param beginTime
     * @param endTime
     * @return
     */
    public static List<Date> findDates(Date beginTime, Date endTime) {
        List<Date> lDate = new ArrayList<Date>();
        lDate.add(beginTime);
        Calendar calBegin = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calBegin.setTime(beginTime);
        Calendar calEnd = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calEnd.setTime(endTime);
        // 测试此日期是否在指定日期之后
        while (endTime.after(calBegin.getTime())) {
            // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
            lDate.add(calBegin.getTime());
            calBegin.add(Calendar.DAY_OF_MONTH, 1);
        }
        return lDate;
    }

    /**
     * 查询一段时间内所有日期
     *
     * @param beginTime
     * @param endTime
     * @return
     */
    public static List<String> findDateStr(Date beginTime, Date endTime) {
        List<String> lDate = new ArrayList<String>();
        Calendar calBegin = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calBegin.setTime(beginTime);
        Calendar calEnd = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calEnd.setTime(endTime);
        // 测试此日期是否在指定日期之后
        while (endTime.after(calBegin.getTime())) {
            // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
            lDate.add(getDateString(calBegin.getTime()));
            calBegin.add(Calendar.DAY_OF_MONTH, 1);
        }
        return lDate;
    }

    /**
     * 获取传入时间的展示格式如：2015年2月第2周
     *
     * @return
     */
    public static String getNextWeekDateName() {

        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, 7);
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH) + 1;
        int week = cal.get(Calendar.DAY_OF_WEEK_IN_MONTH);
        return year + "年" + month + "月第" + week + "周";
    }

    /**
     * 获得下周周一
     *
     * @return
     */
    public static Date getNextWeekMonday() {
        Calendar cal = Calendar.getInstance();
        int n = 1;
        cal.add(Calendar.DATE, n * 7);
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        return cal.getTime();
    }

    /**
     * 获得下周周日
     *
     * @return
     */
    public static Date getNextWeekSunday() {
        Calendar cal = Calendar.getInstance();
        int n = 2;
        cal.add(Calendar.DATE, n * 7);
        cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        return cal.getTime();
    }

    /**
     * 获得week day
     *
     * @param i Calender返回的DAY_OF_WEEK
     * @param prefix 前缀 周 or 星期
     * @return
     */
    public static String getWeekDay(int i, Integer prefix) {
        String day;
        switch (i) {
            case 1:
                day = "天";
                break;
            case 2:
                day = "一";
                break;
            case 3:
                day = "二";
                break;
            case 4:
                day = "三";
                break;
            case 5:
                day = "四";
                break;
            case 6:
                day = "五";
                break;
            case 7:
                day = "六";
                break;
            default:
                day = "日";
                break;
        }
        String prefixStr = prefix == null || prefix == WEEK_PREFIX_ZHOU ? "周" : "星期";
        return prefixStr + day;
    }

    /**
     * 判断日期是否已过去
     *
     * @param date 日期字符串
     * @return boolean
     */
    public static boolean isPast(String date) {
        long nowDateLong = getNowDateLong();
        long dateLong = getDateLong(date);
        return nowDateLong > dateLong;
    }

    /**
     * 判断指定日期是否已过去
     *
     * @param date 日期
     * @param day 日期加减
     * @return boolean
     */
    public static boolean isPast(Date date, int day) {
        long nowDateLong = System.currentTimeMillis();
        long dateLong = date.getTime();
        long pastTime = day * 24 * 60 * 60 * 1000L;
        return nowDateLong > (dateLong + pastTime);
    }

    /**
     * 通过毫秒数获取时间
     *
     * @return
     */
    public static Date getDateByMills(Long mills) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(mills);
        return calendar.getTime();
    }

    public static String format(String pattern, Date date) {
        return getDateFormat(pattern).format(date);
    }

    public static Date parse(String pattern, String date) {
        Date time = new Date();
        try {
            time = getDateFormat(pattern).parse(date);
        } catch (ParseException e) {
            logger.error(e.getMessage());
            e.printStackTrace();
        }
        return time;
    }

    /**
     * 计算两个日期之间相差的天数
     *
     * @param smdate 较小的时间
     * @param bdate 较大的时间
     * @return 相差天数
     */
    public static int daysBetween(Date smdate, Date bdate) {
        return dateBetween(smdate, bdate, DateUtil.DAY);
    }

    /**
     * 计算两个时间之间的差
     *
     * @param smdate 较小的时间
     * @param bdate 较大的时间
     * @param timeType 日、时、分、秒 (DateUtil.DAY,DateUtil.HOUR,DateUtil.MINUTE,DateUtil.SECOND)
     * @return 相差
     * @throws ParseException
     */
    public static int dateBetween(Date smdate, Date bdate, long timeType) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();

        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        long between = (time2 - time1) / (timeType);

        return Integer.parseInt(String.valueOf(between));
    }

    /**
     * 计算两个时间之间的差
     *
     * @param smtime 较小的时间
     * @param btime 较大的时间
     * @param timeType 日、时、分、秒 (DateUtil.DAY,DateUtil.HOUR,DateUtil.MINUTE,DateUtil.SECOND)
     * @return 相差
     * @throws ParseException
     */
    public static int timeBetween(Long smtime, Long btime, long timeType) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(smtime);
        long time1 = cal.getTimeInMillis();

        cal.setTimeInMillis(btime);
        long time2 = cal.getTimeInMillis();
        long between = (time2 - time1) / (timeType);

        return Integer.parseInt(String.valueOf(between));
    }

    /**
     * 字符串的日期格式的计算
     *
     * @param smdate
     * @param bdate
     * @return
     * @throws ParseException
     */
    public static int daysBetween(String smdate, String bdate) throws ParseException {
        return daysBetween(getDateFormat(YYYY_MM_DD).parse(smdate), getDateFormat(YYYY_MM_DD).parse(bdate));
    }

    // add
    public static Date getHourBefore(Date d, int hour) {
        return getTimeBefore(d, hour, Calendar.HOUR);
    }

    public static Date getMinuteBefore(Date d, int minute) {
        return getTimeBefore(d, minute, Calendar.MINUTE);
    }

    /**
     * 获取当前时间前后指定时间
     *
     * @param d 原始日期
     * @param num 增减的数字(之前日期为正;之后日期为负)
     * @param type 类型(Calendar.xxx)
     * @return
     */
    public static Date getTimeBefore(Date d, int num, int type) {
        Calendar now = Calendar.getInstance();
        now.setTime(d);
        now.add(type, -1 * num);
        return now.getTime();
    }

    /**
     * 将秒数/分钟数/小时数 转换为日 时 分秒
     *
     * @param num
     * @param timeType 时、分、秒 (DateUtil.HOUR,DateUtil.MINUTE,DateUtil.SECOND)
     * @return xx 天xx小时xx分钟xx秒;
     */
    public static String changeTime(int num, long timeType) {
        int day;
        int hour;
        int minute;
        int second;
        String res = "";
        if (timeType == DateUtil.SECOND) {
            if (num / 60 < 1) {
                res = num + "秒";
            } else if (num / 60 / 60 < 1) {
                minute = num / 60;
                second = num % 60;
                res = minute + "分钟" + second + "秒";
            } else if (num / 60 / 60 / 24 < 1) {
                hour = num / 60 / 60;
                minute = num % (60 * 60) / 60;
                second = num % (60 * 60) % 60;
                res = hour + "小时" + minute + "分钟" + second + "秒";
            } else {
                day = num / 60 / 60 / 24;
                hour = num % (60 * 60 * 24) / (60 * 60);
                minute = num % (60 * 60 * 24) % (60 * 60) / 60;
                second = num % (60 * 60 * 24) % (60 * 60) % 60;
                res = day + "天" + hour + "小时" + minute + "分钟" + second + "秒";
            }
        } else if (timeType == DateUtil.MINUTE) {
            if (num / 60 < 1) {
                res = num + "分钟";
            } else if (num / 60 / 24 < 1) {
                hour = num / (60);
                minute = num % (60);
                res = hour + "小时" + minute + "分钟";
            } else {
                day = num / 60 / 24;
                hour = num % (60 * 24) / (60);
                minute = num % (60 * 24) % 60;
                res = day + "天" + hour + "小时" + minute + "分钟";
            }
        } else if (timeType == DateUtil.HOUR) {
            if (num / 24 < 1) {
                res = num + "小时";
            } else {
                day = num / 24;
                hour = num % (24);
                res = day + "天" + hour + "小时";
            }
        }
        return res;
    }

    public static int recursionAlgorithm(int n) {
        if (n <= 0) {
            return 0;
        } else if (n <= 2) {
            return 1;
        } else {
            return recursionAlgorithm(n - 2) + recursionAlgorithm(n - 1);
        }
    }

    public static int add(int n) {
        if (n <= 0) {
            return 0;
        } else if (n == 1) {
            return 10;
        } else {
            return add(n - 1) + add(n - 1) - add(n - 3) - 1;
        }
    }

    /**
     * 取得指定日期所在周的第一天
     *
     * @param date
     * @return
     */
    public static Date getFirstDayOfWeek(Date date) {
        Calendar c = new GregorianCalendar();
        c.setFirstDayOfWeek(Calendar.MONDAY);
        c.setTime(date);
        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek()); // Monday
        return c.getTime();
    }

    /**
     * 取得指定日期所在周的最后一天
     *
     * @param date
     * @return
     */
    public static Date getLastDayOfWeek(Date date) {
        Calendar c = new GregorianCalendar();
        c.setFirstDayOfWeek(Calendar.MONDAY);
        c.setTime(date);
        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek() + 6); // Sunday
        return c.getTime();
    }

    public static String getLastDayOfMonth(int year, int month) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        // 设置Calendar月份数为下一个月
        cal.set(Calendar.MONTH, month - 1 + 1);
        // 设置Calendar日期为下一个月一号
        cal.set(Calendar.DAY_OF_MONTH, 1);
        // 设置Calendar日期减一,为本月末
        cal.add(Calendar.DATE, -1);
        return formatDateLong(cal.getTimeInMillis());
    }

    public static String getFirstDayOfMonth(int year, int month) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month - 1);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        return formatDateLong(cal.getTimeInMillis());
    }

    public static String[] getFirstLastDayOfMonth(String time) {
        String begin = "";
        String end = "";
        if (StrUtil.isNotEmpty(time)) {
            String[] ym = time.split("-");
            int year = Integer.parseInt(ym[0]);
            int month = Integer.parseInt(ym[1]);
            begin = DateUtil.getFirstDayOfMonth(year, month);
            end = DateUtil.getLastDayOfMonth(year, month);
        }
        return new String[]{begin, end};
    }

    /**
     * 获取指定时间之后的时间戳
     *
     * @param time
     * @param num
     * @param type
     * @return
     */
    public static long getTimeAfter(long time, int num, int type) {
        Calendar now = Calendar.getInstance();
        now.setTimeInMillis(time);
        now.add(type, num);
        return now.getTimeInMillis();
    }

    /**
     * 获取当前月的第一天
     *
     * @param date
     * @return
     */
    public static String getFirstDay(Date date) {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, 0);
        c.setTime(date);
        c.set(Calendar.DAY_OF_MONTH, 1); // 设置为1号，当前日期即为本月第一天
        String firstDay = getDateString(c.getTime());
        return firstDay;
    }

    /**
     * 获取当前月的最后一天
     *
     * @param date
     * @return
     */
    public static String getLastDay(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
        String lastDay = getDateString(c.getTime());
        return lastDay;
    }

    public static String getWeekDays(int year, int week, int targetNum) {
        // 计算目标周数
        if (week + targetNum > 52) {
            year++;
            week += targetNum - 52;
        } else if (week + targetNum <= 0) {
            year--;
            week += targetNum + 52;
        } else {
            week += targetNum;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();
        // 设置每周的开始日期
        cal.setFirstDayOfWeek(Calendar.SUNDAY);
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.WEEK_OF_YEAR, week);
        cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
        String beginDate = sdf.format(cal.getTime());
        cal.add(Calendar.DAY_OF_WEEK, 6);
        String endDate = sdf.format(cal.getTime());
        return beginDate + "~" + endDate;
    }

    /**
     * 参数时间是否在今天之前
     *
     * @param date
     * @return
     */
    public static boolean beforeNowDate(Date date) {
        return getNowDate().getTime() > date.getTime();
    }

    /**
     * 参数时间是否在今天之前
     *
     * @param date
     * @return
     */
    public static boolean beforeNowDate(String date) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date time;
        try {
            time = simpleDateFormat.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
            throw new RuntimeException("时间格式化失败");
        }
        return beforeNowDate(time);
    }

    /**
     * 返回 日期 的星期
     *
     * @param date 日期
     * @param prefix 0-周x ；1-星期x
     * @return
     */
    public static String getWeekByDate(Date date, Integer prefix) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int i = c.get(Calendar.DAY_OF_WEEK);
        return getWeekDay(i, prefix);
    }

    /**
     * 返回周x
     *
     * @param date 日期
     * @return
     */
    public static String getWeekByDate(Date date) {
        return getWeekByDate(date, null);
    }

    /**
     * 日期 按中文习惯展示，并对比当前日期，除 今、明、后、昨 天外，其余返回周x或者星期x
     *
     * @param date 日期
     * @param prefix 前缀
     * @return
     */
    public static String getWeekByDateLimitFour(Date date, Integer prefix) {
        return getWeekByDateLimit(date, prefix, 4);
    }

    /**
     * 日期 按中文习惯展示，并对比当前日期，除 今、明、后、昨 天外，其余返回周x或者星期x
     *
     * @param date 日期
     * @param prefix 前缀
     * @param maxDateBetween 3-(昨、今、明);4-(昨、今、明、后)
     * @return
     */
    public static String getWeekByDateLimit(Date date, Integer prefix, int maxDateBetween) {
        int i = DateUtil.daysBetween(date, getNowDate());
        i = maxDateBetween == 3 && i == -2 ? -3 : i;
        String desc;
        switch (i) {
            case -2:
                desc = " 后天";
                break;
            case -1:
                desc = " 明天";
                break;
            case 0:
                desc = " 今天";
                break;
            case 1:
                desc = " 昨天";
                break;
            default:
                desc = DateUtil.getWeekByDate(date, prefix);
        }
        return desc;
    }

    /**
     * 日期 按中文习惯展示，并对比当前日期，除 今、明、昨 天外，其余返回周x或者星期x
     *
     * @param date 日期
     * @param prefix 前缀
     * @return
     */
    public static String getWeekByDateLimitThree(Date date, Integer prefix) {
        return getWeekByDateLimit(date, prefix, 3);
    }

    /**
     * 日期 按中文习惯展示，并对比当前日期，除 今、明、昨 天外，其余返回周x
     *
     * @param date 日期
     * @return
     */
    public static String getWeekByDateLimitThree(Date date) {
        return getWeekByDateLimitThree(date, null);
    }

    /**
     * 日期 按中文习惯展示，并对比当前日期，除 今、明、后、昨 天外，其余返回周x
     *
     * @param date 日期
     * @return
     */
    public static String getWeekByDateLimitFour(Date date) {
        return getWeekByDateLimitFour(date, null);
    }

    public static void main(String[] args) {
        System.out.println(getWeekByDate(getNowDate()));
    }

}